package com.toivan.mt.utils;

import android.opengl.GLES20;
import android.util.Log;

import com.toivan.sdk.egl.MtGLUtils;

import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;

public class RGBAToNV21Renderer {
    private String TAG = RGBAToNV21Renderer.class.getSimpleName();
    private final String vertexShaderSource = "attribute vec4 aPosition;\nattribute vec4 aTextureCoord;\nvarying vec2 vTextureCoord;\nvoid main() {\n    gl_Position = aPosition;\n    vTextureCoord = aTextureCoord.xy;\n}\n";
    private final String fragmentShaderSource = "#version 100\n\n                precision highp float;\n                precision highp int;\n\n                varying vec2 vTextureCoord;\n                uniform sampler2D uTexture;\n\n                uniform float uWidth;\n                uniform float uHeight;\n\n                float cY(float x, float y) {\n                    vec4 c = texture2D(uTexture, vec2(x, y));\n                    return c.r * 0.257 + c.g * 0.504 + c.b * 0.098 + 0.0625;\n                }\n\n                vec4 cC(float x, float y, float dx, float dy) {\n                    vec4 c0 = texture2D(uTexture, vec2(x, y));\n                    vec4 c1 = texture2D(uTexture, vec2(x + dx, y));\n                    vec4 c2 = texture2D(uTexture, vec2(x, y + dy));\n                    vec4 c3 = texture2D(uTexture, vec2(x + dx, y + dy));\n                    return (c0 + c1 + c2 + c3) / 4.;\n                }\n\n                float cU(float x, float y, float dx, float dy) {\n                    vec4 c = cC(x, y, dx, dy);\n                    return -0.148 * c.r - 0.291 * c.g + 0.439 * c.b + 0.5000;\n                }\n\n                float cV(float x, float y, float dx, float dy) {\n                    vec4 c = cC(x, y, dx, dy);\n                    return 0.439 * c.r - 0.368 * c.g - 0.071 * c.b + 0.5000;\n                }\n\n                vec2 cPos(float t, float shiftx, float gy) {\n                    vec2 pos = vec2(floor(uWidth * vTextureCoord.x), floor(uHeight * gy));\n                    return vec2(mod(pos.x * shiftx, uWidth), (pos.y * shiftx + floor(pos.x * shiftx / uWidth)) * t);\n                }\n\n                vec4 calculateY() {\n                    vec2 pos = cPos(1., 4., vTextureCoord.y);\n                    vec4 oColor = vec4(0);\n                    float textureYPos = pos.y / uHeight;\n                    oColor[0] = cY(pos.x / uWidth, textureYPos);\n                    oColor[1] = cY((pos.x + 1.) / uWidth, textureYPos);\n                    oColor[2] = cY((pos.x + 2.) / uWidth, textureYPos);\n                    oColor[3] = cY((pos.x + 3.) / uWidth, textureYPos);\n                    return oColor;\n                }\n\n                 vec4 calculateVU(float dx, float dy) {\n                    vec2 pos = cPos(2., 4., vTextureCoord.y - 0.2500);\n                    vec4 oColor = vec4(0);\n                    float textureYPos = pos.y / uHeight;\n                    oColor[0] = cV(pos.x / uWidth, textureYPos, dx, dy);\n                    oColor[1] = cU(pos.x / uWidth, textureYPos, dx, dy);\n                    oColor[2] = cV((pos.x + 2.) / uWidth, textureYPos, dx, dy);\n                    oColor[3] = cU((pos.x + 2.) / uWidth, textureYPos, dx, dy);\n                    return oColor;\n                }\n\n                vec4 calculateUV(float dx, float dy) {\n                    vec2 pos = cPos(2., 4., vTextureCoord.y - 0.2500);\n                    vec4 oColor = vec4(0);\n                    float textureYPos = pos.y / uHeight;\n                    oColor[0] = cU(pos.x / uWidth, textureYPos, dx, dy);\n                    oColor[1] = cV(pos.x / uWidth, textureYPos, dx, dy);\n                    oColor[2] = cU((pos.x + 2.) / uWidth, textureYPos, dx, dy);\n                    oColor[3] = cV((pos.x + 2.) / uWidth, textureYPos, dx, dy);\n                    return oColor;\n                }\n\n                void main() {\n                    if (vTextureCoord.y < 0.2500) {\n                        gl_FragColor = calculateY();\n                    } else if (vTextureCoord.y < 0.3750) {\n                        gl_FragColor = calculateVU(1. / uWidth, 1. / uHeight);\n                    } else {\n                        gl_FragColor = vec4(0, 0, 0, 0);\n                    }\n                }";
    private float[] vertex = new float[]{-1.0F, -1.0F, -1.0F, 1.0F, 1.0F, 1.0F, 1.0F, -1.0F};
    private float[] texture = new float[]{0.0F, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F, 1.0F, 0.0F};
    private int[] indices = new int[]{0, 1, 2, 0, 2, 3};
    private FloatBuffer vertexBuffer;
    private FloatBuffer textureBuffer;
    private IntBuffer indicesBuffer;
    private int program;
    private int positionLocation;
    private int textureCoordLocation;
    private int textureLocation;
    private int imageWidth;
    private int imageHeight;
    private int[] frameBufferId = new int[1];
    private int[] frameBufferTextureId = new int[1];
    private boolean isCreate = false;
    private int uWidthLocation;
    private int uHeightLocation;

    public RGBAToNV21Renderer(int var1, int var2) {
        this.imageWidth = var1;
        this.imageHeight = var2;
    }

    public void create() {
        RGBAToNV21Renderer var10000 = this;
        RGBAToNV21Renderer var10001 = this;
        RGBAToNV21Renderer var10002 = this;
        FloatBuffer var1;
        FloatBuffer var10020 = var1 = ByteBuffer.allocateDirect(this.vertex.length * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
        this.vertexBuffer = var1;
        var10020.put(this.vertex).position(0);
        FloatBuffer var10019 = var1 = ByteBuffer.allocateDirect(this.texture.length * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
        this.textureBuffer = var1;
        var10019.put(this.texture).position(0);
        IntBuffer var3;
        IntBuffer var10018 = var3 = ByteBuffer.allocateDirect(this.indices.length * 4).order(ByteOrder.nativeOrder()).asIntBuffer();
        this.indicesBuffer = var3;
        var10018.put(this.indices).position(0);
        GLES20.glUseProgram(this.program = MtGLUtils.loadProgram("attribute vec4 aPosition;\nattribute vec4 aTextureCoord;\nvarying vec2 vTextureCoord;\nvoid main() {\n    gl_Position = aPosition;\n    vTextureCoord = aTextureCoord.xy;\n}\n", "#version 100\n\n                precision highp float;\n                precision highp int;\n\n                varying vec2 vTextureCoord;\n                uniform sampler2D uTexture;\n\n                uniform float uWidth;\n                uniform float uHeight;\n\n                float cY(float x, float y) {\n                    vec4 c = texture2D(uTexture, vec2(x, y));\n                    return c.r * 0.257 + c.g * 0.504 + c.b * 0.098 + 0.0625;\n                }\n\n                vec4 cC(float x, float y, float dx, float dy) {\n                    vec4 c0 = texture2D(uTexture, vec2(x, y));\n                    vec4 c1 = texture2D(uTexture, vec2(x + dx, y));\n                    vec4 c2 = texture2D(uTexture, vec2(x, y + dy));\n                    vec4 c3 = texture2D(uTexture, vec2(x + dx, y + dy));\n                    return (c0 + c1 + c2 + c3) / 4.;\n                }\n\n                float cU(float x, float y, float dx, float dy) {\n                    vec4 c = cC(x, y, dx, dy);\n                    return -0.148 * c.r - 0.291 * c.g + 0.439 * c.b + 0.5000;\n                }\n\n                float cV(float x, float y, float dx, float dy) {\n                    vec4 c = cC(x, y, dx, dy);\n                    return 0.439 * c.r - 0.368 * c.g - 0.071 * c.b + 0.5000;\n                }\n\n                vec2 cPos(float t, float shiftx, float gy) {\n                    vec2 pos = vec2(floor(uWidth * vTextureCoord.x), floor(uHeight * gy));\n                    return vec2(mod(pos.x * shiftx, uWidth), (pos.y * shiftx + floor(pos.x * shiftx / uWidth)) * t);\n                }\n\n                vec4 calculateY() {\n                    vec2 pos = cPos(1., 4., vTextureCoord.y);\n                    vec4 oColor = vec4(0);\n                    float textureYPos = pos.y / uHeight;\n                    oColor[0] = cY(pos.x / uWidth, textureYPos);\n                    oColor[1] = cY((pos.x + 1.) / uWidth, textureYPos);\n                    oColor[2] = cY((pos.x + 2.) / uWidth, textureYPos);\n                    oColor[3] = cY((pos.x + 3.) / uWidth, textureYPos);\n                    return oColor;\n                }\n\n                 vec4 calculateVU(float dx, float dy) {\n                    vec2 pos = cPos(2., 4., vTextureCoord.y - 0.2500);\n                    vec4 oColor = vec4(0);\n                    float textureYPos = pos.y / uHeight;\n                    oColor[0] = cV(pos.x / uWidth, textureYPos, dx, dy);\n                    oColor[1] = cU(pos.x / uWidth, textureYPos, dx, dy);\n                    oColor[2] = cV((pos.x + 2.) / uWidth, textureYPos, dx, dy);\n                    oColor[3] = cU((pos.x + 2.) / uWidth, textureYPos, dx, dy);\n                    return oColor;\n                }\n\n                vec4 calculateUV(float dx, float dy) {\n                    vec2 pos = cPos(2., 4., vTextureCoord.y - 0.2500);\n                    vec4 oColor = vec4(0);\n                    float textureYPos = pos.y / uHeight;\n                    oColor[0] = cU(pos.x / uWidth, textureYPos, dx, dy);\n                    oColor[1] = cV(pos.x / uWidth, textureYPos, dx, dy);\n                    oColor[2] = cU((pos.x + 2.) / uWidth, textureYPos, dx, dy);\n                    oColor[3] = cV((pos.x + 2.) / uWidth, textureYPos, dx, dy);\n                    return oColor;\n                }\n\n                void main() {\n                    if (vTextureCoord.y < 0.2500) {\n                        gl_FragColor = calculateY();\n                    } else if (vTextureCoord.y < 0.3750) {\n                        gl_FragColor = calculateVU(1. / uWidth, 1. / uHeight);\n                    } else {\n                        gl_FragColor = vec4(0, 0, 0, 0);\n                    }\n                }"));
        this.positionLocation = GLES20.glGetAttribLocation(this.program, "aPosition");
        this.textureCoordLocation = GLES20.glGetAttribLocation(this.program, "aTextureCoord");
        this.textureLocation = GLES20.glGetUniformLocation(this.program, "uTexture");
        this.uWidthLocation = GLES20.glGetUniformLocation(this.program, "uWidth");
        this.uHeightLocation = GLES20.glGetUniformLocation(this.program, "uHeight");
        GLES20.glGenFramebuffers(1, this.frameBufferId, 0);
        GLES20.glBindFramebuffer(36160, this.frameBufferId[0]);
        GLES20.glGenTextures(1, this.frameBufferTextureId, 0);
        GLES20.glBindTexture(3553, this.frameBufferTextureId[0]);
        int var2 = this.imageWidth;
        int var4 = var10002.imageHeight;
        GLES20.glTexImage2D(3553, 0, 6408, var2, var4, 0, 6408, 5121, (Buffer)null);
        GLES20.glTexParameterf(3553, 10240, 9729.0F);
        GLES20.glTexParameterf(3553, 10241, 9729.0F);
        GLES20.glTexParameterf(3553, 10242, 33071.0F);
        GLES20.glTexParameterf(3553, 10243, 33071.0F);
        var2 = var10001.frameBufferTextureId[0];
        GLES20.glFramebufferTexture2D(36160, 36064, 3553, var2, 0);
        GLES20.glBindFramebuffer(36160, 0);
        GLES20.glUseProgram(0);
        var10000.isCreate = true;
    }

    public void render(int var1, ByteBuffer var2) {
        if (var1 == 0 || !this.isCreate) {
            Log.e(this.TAG, "input valid textureId or create first");
        }

        RGBAToNV21Renderer var10000 = this;
        RGBAToNV21Renderer var10001 = this;
        RGBAToNV21Renderer var10002 = this;
        RGBAToNV21Renderer var10003 = this;
        RGBAToNV21Renderer var10004 = this;
        RGBAToNV21Renderer var10005 = this;
        GLES20.glBindFramebuffer(36160, this.frameBufferId[0]);
        GLES20.glUseProgram(this.program);
        GLES20.glClearColor(1.0F, 1.0F, 1.0F, 0.0F);
        GLES20.glClear(16384);
        int var3 = this.imageWidth;
        int var4 = this.imageHeight;
        GLES20.glViewport(0, 0, var3, var4);
        GLES20.glActiveTexture(33984);
        GLES20.glBindTexture(3553, var1);
        GLES20.glUniform1i(this.textureLocation, 0);
        GLES20.glUniform1f(this.uWidthLocation, (float)this.imageWidth);
        GLES20.glUniform1f(this.uHeightLocation, (float)this.imageHeight);
        this.vertexBuffer.position(0);
        FloatBuffer var8 = this.vertexBuffer;
        GLES20.glVertexAttribPointer(this.positionLocation, 2, 5126, false, 0, var8);
        GLES20.glEnableVertexAttribArray(this.positionLocation);
        this.textureBuffer.position(0);
        int var10006 = this.textureCoordLocation;
        FloatBuffer var5 = this.textureBuffer;
        GLES20.glVertexAttribPointer(var10006, 2, 5126, false, 0, var5);
        GLES20.glEnableVertexAttribArray(var10005.textureCoordLocation);
        IntBuffer var6 = var10004.indicesBuffer;
        GLES20.glDrawElements(4, 6, 5125, var6);
        int var7 = var10003.imageWidth;
        var1 = var10002.imageHeight * 3 / 8;
        GLES20.glReadPixels(0, 0, var7, var1, 6408, 5121, var2);
        GLES20.glDisableVertexAttribArray(var10001.positionLocation);
        GLES20.glDisableVertexAttribArray(var10000.textureCoordLocation);
        GLES20.glBindTexture(3553, 0);
        GLES20.glUseProgram(0);
        GLES20.glBindFramebuffer(36160, 0);
    }

    public void destroy() {
        this.isCreate = false;
        GLES20.glDeleteProgram(this.program);
        GLES20.glDeleteFramebuffers(1, this.frameBufferId, 0);
    }
}
